#include "src/include/Socket.h"
#include <cstring>
#include <stdexcept>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>

//#pragma comment(lib, "ws2_32.lib")

// 错误处理函数
void printError(bool condition, const char* message) {
    if (condition) {
        std::cerr << message << ": " << WSAGetLastError() << std::endl;
        throw std::runtime_error(message);
    }
}

Socket::Socket()
{
    // 初始化Winsock
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printError(true, "WSAStartup failed");
    }

    fd_ = socket(AF_INET, SOCK_STREAM, 0);
    printError(fd_ == static_cast<int>(INVALID_SOCKET) , "socket creation failed");
}

Socket::Socket(int fd) : fd_(fd)
{
    setNonBlocking();
}

void Socket::Bind(InetAddress *addr)
{
    sockaddr_in addr_in = addr->getAddr();
    printError(bind(fd_, (sockaddr*)&addr_in, sizeof(addr_in)) == SOCKET_ERROR, "bind failed");
}

void Socket::Listen()
{
    printError(listen(fd_, SOMAXCONN) == SOCKET_ERROR, "listen failed");
}

void Socket::setNonBlocking()
{
    unsigned long mode = 1; // 1表示非阻塞，0表示阻塞
    printError(ioctlsocket(fd_, FIONBIO, &mode) == SOCKET_ERROR, "setNonBlocking failed");
}

bool Socket::isNonBlocking()
{
    unsigned long mode = 0;
    if (ioctlsocket(fd_, FIONBIO, &mode) == SOCKET_ERROR) {
        return false;
    }
    return mode != 0;
}

int Socket::getFd()
{
    return fd_;
}

int Socket::Accept(InetAddress *addr)
{
    int clnt_fd = -1;
    sockaddr_in clnt_addr = {};
    int clnt_len = sizeof(clnt_addr);

    // 判断是否为非阻塞模式
    if (isNonBlocking()) {
        while (true) {
            clnt_fd = accept(fd_, (sockaddr*)&clnt_addr, &clnt_len);
            if (clnt_fd == static_cast<int>(INVALID_SOCKET) && (WSAGetLastError() == WSAEWOULDBLOCK)) {
                continue;
            }
            break;
        }
    } else {
        clnt_fd = accept(fd_, (sockaddr*)&clnt_addr, &clnt_len);
    }

    if (clnt_fd != static_cast<int>(INVALID_SOCKET)) {
        addr->setsockaddr(clnt_addr);
    }

    return clnt_fd;
}

bool Socket::Connect(const InetAddress &serverAddr)
{
    const sockaddr_in& addr = serverAddr.getAddr(); // 保存引用
    if (connect(fd_, reinterpret_cast<const sockaddr*>(&addr), sizeof(sockaddr_in)) == SOCKET_ERROR) {
        std::cerr << "Connect failed: " << WSAGetLastError() << std::endl;
        return false;
    }
    return true;
}

Socket::~Socket()
{
    if (fd_ != -1) {
        closesocket(fd_);
        fd_ = -1;
    }

    // 清理Winsock
    WSACleanup();
}

InetAddress::InetAddress()
{
    memset(&addr_, 0, sizeof(addr_));
    addr_.sin_family = AF_INET;
    addr_.sin_addr.s_addr = INADDR_ANY;
    addr_.sin_port = 0;
}

InetAddress::InetAddress(const char *ip, uint16_t port)
{
    memset(&addr_, 0, sizeof(addr_));
    addr_.sin_family = AF_INET;

    if (ip != nullptr) {
        addr_.sin_addr.s_addr = inet_addr(ip);
        if (addr_.sin_addr.s_addr == INADDR_NONE) {
            // 处理无效IP地址
            addr_.sin_addr.s_addr = INADDR_ANY;
        }
    } else {
        addr_.sin_addr.s_addr = INADDR_ANY;
    }

    addr_.sin_port = htons(port);
}

void InetAddress::setsockaddr(sockaddr_in addr)
{
    addr_ = addr;
}

const char* InetAddress::getIp()
{
    return inet_ntoa(addr_.sin_addr);
}

uint16_t InetAddress::getPort()
{
    return ntohs(addr_.sin_port);
}

const sockaddr_in InetAddress::getAddr() const
{
    return addr_;
}

InetAddress::~InetAddress()
{
    // 不需要特殊清理
}
